<html>
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="lib/require.js"></script>
        <script type="text/javascript" src="lib/stats.js"></script>
        <script type="text/javascript" src="lib/dat.gui.js"></script>
    </head>
    <body style="margin:0px;">
        <style>
            #main {
                background: #000;
            }
        </style>
        <canvas id="main"></canvas>
        <script type="text/javascript">
            require(['../dist/claygl', 'js/SSRPass', 'js/createCompositor'], function(clay, SSRPass, createCompositor) {

                var config = {
                    maxIteration: 16,
                    maxBinarySearchIteration: 5,
                    maxRayDistance: 4,
                    pixelStride: 16,
                    pixelStrideZCutoff: 50,
                    screenEdgeFadeStart: 0.9,
                    eyeFadeStart: 0.4,
                    eyeFadeEnd: 0.8,

                    roughness: 0.5
                };

                var renderer = new clay.Renderer({
                    canvas: document.getElementById('main'),
                    devicePixelRatio: 1.0
                });
                var camera = new clay.camera.Perspective({
                    aspect: renderer.getViewportAspect()
                });
                camera.position.set(0, 4, 4);
                camera.lookAt(clay.Vector3.ZERO);

                var gBuffer = new clay.deferred.GBuffer();
                var ssrPass = new SSRPass({
                    gBuffer: gBuffer,
                    renderToTexture: true,
                    RGBM: true
                });

                var scene = new clay.Scene();
                var planeGeo = new clay.geometry.Plane();
                var plane = new clay.Mesh({
                    geometry: planeGeo,
                    material: new clay.Material({
                        shader: clay.shader.library.get('clay.standard', {
                            textures: ['diffuseMap', 'normalMap'],
                            fragmentDefines: {
                                RGBM_ENCODE: null,
                                SRGB_DECODE: null,
                                USE_ROUGHNESS: null
                            }
                        })
                    })
                });
                plane.scale.set(10, 10, 1);
                plane.rotation.rotateX(-Math.PI / 2);
                // plane.material.set('color', [0.2, 0.2, 0.2]);

                var diffuseTex = new clay.Texture2D({
                    wrapS: clay.Texture.REPEAT,
                    wrapT: clay.Texture.REPEAT
                });
                var normalTex = new clay.Texture2D({
                    wrapS: clay.Texture.REPEAT,
                    wrapT: clay.Texture.REPEAT
                });
                diffuseTex.load('assets/textures/oakfloor2/oakfloor2_basecolor.png');
                normalTex.load('assets/textures/oakfloor2/oakfloor2_normal.png');
                plane.geometry.generateTangents();
                plane.material.set('diffuseMap', diffuseTex);
                plane.material.set('normalMap', normalTex);
                plane.material.set('uvRepeat', [5, 5]);

                scene.add(plane);
                var mainLight = new clay.light.Directional({
                    intensity: 1
                });
                mainLight.position.set(10, 10, 10);
                mainLight.lookAt(scene.position);
                scene.add(mainLight);

                var loader = new clay.loader.GLTF();
                loader.load('assets/models/suzanne/suzanne_high.gltf');
                var suzanneGeometry;
                loader.on('success', function(res) {
                    suzanneGeometry = res.scene.getNode('Suzanne').geometry;

                    var envMap = clay.util.texture.loadTexture(
                        'assets/textures/hdr/pisa.hdr',
                        {
                            exposure: 3
                        },
                        function () {
                            envMap.flipY = false;

                            var prefilterResult = clay.util.cubemap.prefilterEnvironmentMap(
                                renderer, envMap, {
                                    width: 128,
                                    height: 128
                                }
                            );

                            var skybox = new clay.plugin.Skybox({
                                scene: scene
                            });
                            skybox.material.set('environmentMap', prefilterResult.environmentMap);
                            skybox.material.define('fragment', 'RGBM_ENCODE');

                            var shader = clay.shader.library.get(
                                'clay.standard', {
                                    textures: [
                                        'environmentMap', 'brdfLookup',
                                        'diffuseMap', 'normalMap', 'metalnessMap', 'roughnessMap'
                                    ],
                                    fragmentDefines: {
                                        ENVIRONMENTMAP_PREFILTER: null,
                                        RGBM_ENCODE: null,
                                        USE_METALNESS: null,
                                        USE_ROUGHNESS: null,
                                        SRGB_DECODE: null
                                    }
                                }
                            );

                            var material = new clay.Material({
                                shader: shader
                            });
                            var mesh = new clay.Mesh({
                                geometry: suzanneGeometry,
                                material: material
                            });
                            mesh.geometry.generateTangents();

                            material.set('maxMipmapLevel', prefilterResult.maxMipmapLevel);
                            material.set('brdfLookup', prefilterResult.brdfLookup);
                            material.set('environmentMap', prefilterResult.environmentMap);
                            material.set('roughness', 0.4);
                            material.set('metalness', 0.5);
                            material.set('uvRepeat', [2, 2]);

                            [ ['diffuseMap', 'basecolor'], ['normalMap', 'normal'], ['metalnessMap', 'metalness'], ['roughnessMap', 'roughness'] ].forEach(function (mapInfo) {
                                var tex = new clay.Texture2D({
                                    wrapS: clay.Texture.REPEAT,
                                    wratT: clay.Texture.REPEAT
                                });
                                tex.load('assets/textures/iron-rusted4/iron-rusted4-' + mapInfo[1] + '.png')
                                    .success(function () {
                                        tex.wrapS = clay.Texture.REPEAT;
                                        tex.wrapT = clay.Texture.REPEAT;
                                    });
                                material.set(mapInfo[0], tex);
                            });

                            mesh.scale.set(1, 1, 1);
                            mesh.position.y = 1;
                            scene.add(mesh);
                        });
                });

                var control = new clay.plugin.OrbitControl({
                    target: camera,
                    domElement: renderer.canvas
                });

                var frameBuffer = new clay.FrameBuffer();
                var colorTex = new clay.Texture2D();
                var timeline =  new clay.Timeline();
                timeline.start();

                var compositor = createCompositor({
                    texture: ssrPass.getTargetTexture()
                });
                timeline.on('frame', function(deltaTime) {
                    control.update(deltaTime);

                    frameBuffer.attach(colorTex);
                    frameBuffer.bind(renderer);
                    renderer.render(scene, camera);
                    frameBuffer.unbind(renderer);

                    gBuffer.update(renderer, scene, camera);
                    ssrPass.render(renderer, camera, colorTex);


                    compositor.render(renderer);
                });

                window.onresize = function() {
                    var width = window.innerWidth;
                    var height = window.innerHeight;
                    renderer.resize(width, height);
                    gBuffer.resize(width, height);
                    colorTex.width = width;
                    colorTex.height = height;
                    colorTex.dirty();
                    camera.aspect = renderer.getViewportAspect();
                };
                window.onresize();

                function updateConfig() {
                    for (var name in config) {
                        ssrPass.setParameter(name, config[name]);
                    }
                }
                updateConfig();

                var gui = new dat.GUI();
                gui.add(config, 'maxIteration', 0, 200).step(1).onChange(updateConfig);
                gui.add(config, 'maxBinarySearchIteration', 0, 20).step(1).onChange(updateConfig);
                gui.add(config, 'maxRayDistance', 0, 10).onChange(updateConfig);
                gui.add(config, 'pixelStride', 0, 32).onChange(updateConfig);
                gui.add(config, 'pixelStrideZCutoff', 0, 50).onChange(updateConfig);
                gui.add(config, 'screenEdgeFadeStart', 0, 1).onChange(updateConfig);
                gui.add(config, 'eyeFadeStart', 0, 1).onChange(updateConfig);
                gui.add(config, 'eyeFadeEnd', 0, 1).onChange(updateConfig);
                gui.add(config, 'roughness', 0, 1).onChange(function (val) {
                    plane.material.set('roughness', val);
                });
            });
        </script>
</html>